﻿using System;
using System.Text;

namespace BGShell.PowerShell.LanguageService
{
    partial class TabExpansionHandler
    {
        private sealed class LastWord
        {
            private readonly String _line;
            private readonly StringBuilder _result;

            private int _lineIndex;
            private int _replacementIndex;
            private string _closingQuote;

            internal LastWord(string line)
            {
                _line = line;
                _result = new StringBuilder(line.Length);

                bool inLastWord = false;
                bool inSingleQuote = false;
                bool inDoubleQuote = false;

                while (_lineIndex < _line.Length)
                {
                    char c = _line[_lineIndex];

                    if (SpecialCharacters.IsSingleQuote(c))
                    {
                        HandleQuote(c, ref inSingleQuote, ref inDoubleQuote, ref inLastWord);
                    }
                    else if (SpecialCharacters.IsDoubleQuote(c))
                    {
                        HandleQuote(c, ref inDoubleQuote, ref inSingleQuote, ref inLastWord);
                    }
                    else if (SpecialCharacters.IsBacktick(c))
                    {
                        Append(c);

                        if (++_lineIndex < _line.Length)
                        {
                            Append(_line[_lineIndex]);
                        }
                    }
                    else
                    {
                        if (IsWhitespace(c))
                        {
                            if (inLastWord)
                            {
                                inLastWord = false;

                                inSingleQuote = false;
                                inDoubleQuote = false;

                                ReplacementIndex = _lineIndex + 1;
                            }
                            else if (inSingleQuote || inDoubleQuote)
                            {
                                Append(c);
                            }
                            else
                            {
                                ReplacementIndex = _lineIndex + 1;
                            }
                        }
                        else
                        {
                            Append(c);
                        }
                    }

                    _lineIndex++;
                }

                if (inSingleQuote)
                {
                    _closingQuote = "'";
                }
                else if (inDoubleQuote)
                {
                    _closingQuote = "\"";
                }
            }

            public string Value
            {
                get { return _result.ToString(); }
            }

            public string ClosingQuote
            {
                get { return _closingQuote; }
            }

            public int ReplacementIndex
            {
                get { return _replacementIndex; }
                private set
                {
                    _result.Length = 0;
                    _replacementIndex = value;
                }
            }

            private void Append(char c)
            {
                _result.Append(c);
            }

            private void HandleQuote(char c, ref bool inQuote, ref bool inOppositeQuote, ref bool inLastWord)
            {
                if (inOppositeQuote)
                {
                    Append(c);
                }
                else if (inQuote)
                {
                    if (inLastWord)
                    {
                        ReplacementIndex = _lineIndex + 1;
                    }
                    
                    inLastWord = !inLastWord;
                }
                else
                {
                    inQuote = true;
                    ReplacementIndex = _lineIndex + 1;
                }
            }

            private static bool IsWhitespace(char c)
            {
                return c == '\t' || c == ' ';
            }
        }
    }
}
